package com.ddw.meedeeuh.shared.movie.scrapers.tmdb;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.ddw.meedeeuh.shared.http.HttpException;
import com.ddw.meedeeuh.shared.http.HttpUtils;
import com.ddw.meedeeuh.shared.io.SourceFile;
import com.ddw.meedeeuh.shared.movie.MovieSettings;
import com.ddw.meedeeuh.shared.movie.scrapers.MovieFileUtils;
import com.ddw.meedeeuh.shared.movie.scrapers.SearchMovieResult;
import com.ddw.meedeeuh.shared.movie.scrapers.SearchMovieScraper;
import com.ddw.meedeeuh.shared.movie.scrapers.SearchMovieScraperResult;
import com.ddw.meedeeuh.shared.movie.scrapers.SearchMovieScraperResultFactory;
import com.ddw.meedeeuh.shared.movie.scrapers.MovieScraperResultType;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;

class TmdbSearchMovieScraper implements SearchMovieScraper {

	private static Logger LOGGER = Logger.getLogger(TmdbSearchMovieScraper.class.getName());
	private static String TMDB_SEARCH_API_URL = "http://api.themoviedb.org/3/search/movie?api_key=%s&query=%s&year=%d";

	@Override
	public SearchMovieScraperResult scrape(MovieSettings settings, SourceFile file) {
		LOGGER.finer("Entering Tmdb Search Movie Scraper");

		// Get the movie name
		LOGGER.finest("Extracting movie name");
		final String movieName = MovieFileUtils.extractMovieName(file, settings);
		LOGGER.finer("Extracted movie name: " + (movieName == null ? "NULL" : movieName));

		// Get the movie year
		LOGGER.finest("Extracting movie year");
		final Integer movieYear = MovieFileUtils.extractMovieYear(file, settings);
		LOGGER.finer("Extracted movie year: " + (movieYear == null ? "NULL" : movieYear.toString()));

		// Check scraped name
		if(movieName == null || movieName.isEmpty()) {
			LOGGER.finer("Movie name was null or empty, exiting Tmdb Movie Scraper");
			return SearchMovieScraperResultFactory.create(MovieScraperResultType.FAILED_PARSE);
		}

		// Check scraped year
		if(movieYear == null || movieYear < 1900) {
			LOGGER.finer("Movie year was null or invalid, exiting Tmdb Movie Scraper");
			return SearchMovieScraperResultFactory.create(MovieScraperResultType.FAILED_PARSE);
		}

		// Contact tmdb api to search for movie
		LOGGER.finest("Retrieving api search json");
		final String response;
		try {
			response = getSearchJson(settings.getTmdbApiKey(), movieName, movieYear);
		} catch (Exception e) {
			LOGGER.log(Level.SEVERE, "Failed to retrieve api search json", e);
			return SearchMovieScraperResultFactory.create(MovieScraperResultType.FAILED_NETWORK);
		}
		LOGGER.finest("Finished retrieving api search json");

		// Convert the string into json
		LOGGER.finest("Converting json response");
		final JsonSearchResponse json;
		try {
			json = new Gson().fromJson(response, JsonSearchResponse.class);
		} catch (JsonParseException e) {
			LOGGER.log(Level.SEVERE, "Failed to convert response to json", e);
			return SearchMovieScraperResultFactory.create(MovieScraperResultType.FAILED_PARSE);
		}

		// Parse the json into matched movies
		LOGGER.finest("Parsing json movies");
		final List<SearchMovieResult> movies = parseMovies(file, json, movieYear);
		LOGGER.finest("Finished parsing results, " + movies.size() + " movies found");

		LOGGER.finer("Exiting Tmdb Search Movie Scraper");
		return SearchMovieScraperResultFactory.create(MovieScraperResultType.SUCCESS, movies);
	}

	private List<SearchMovieResult> parseMovies(SourceFile file, JsonSearchResponse json, int year) {
		final List<SearchMovieResult> movies = new ArrayList<SearchMovieResult>();
		for(final JsonSearchResponseMovie movie : json.results) {
			movies.add(TmdbSearchMovieResultFactory.create(file, movie.id, movie.title, year));
		}
		return movies;
	}

	private String getSearchJson(String apiKey, String movieName, int movieYear) throws HttpException {
		LOGGER.finest("Creating tmdb api url");
		final String url = String.format(TMDB_SEARCH_API_URL, apiKey, HttpUtils.encode(movieName), movieYear);
		LOGGER.finest("Requesting json at " + url);
		final String json = HttpUtils.get(url);
		LOGGER.finer("Request returned " + json.length() + " characters");
		return json;
	}

	class JsonSearchResponse {

		int page;
		int total_results;
		int total_pages;
		List<JsonSearchResponseMovie> results;

		JsonSearchResponse() {}

	}

	class JsonSearchResponseMovie {

		String backdrop_path;
		int id;
		String original_title;
		double popularity;
		String poster_path;
		String release_date;
		String title;

		JsonSearchResponseMovie() {}

	}

}
